let output_set list options reference =
  match list with
      [] -> Printf.printf "-o waits for a string\n";exit 0
    | e::l when List.mem e options -> Printf.printf "-o waits for a string\n"; exit 0
    | e::l -> reference := e; l

let line_set list options line =
  match list with
      [] -> Printf.printf "-l waits for a int\n"; exit 0
    | e::l when List.mem e options -> Printf.printf "-l waits for a int\n"; exit 0
    | e::l -> line := int_of_string e; l

let conv_string_set list options conv_string =
  match list with
      [] -> Printf.printf "-s waits for string\n";exit 0
    | e::l when List.mem e options -> Printf.printf "-s waits for string\n"; exit 0
    | e::l -> conv_string := " "^e; l

let ratio_set list options rlist =
  match list with
      [] -> Printf.printf "-r waits for two int\n"; exit 0
    | e::[] -> Printf.printf "-r waits for two int\n"; exit 0
    | e::x::l when (List.mem e options || List.mem x options) -> Printf.printf "-r waits for two int\n"; exit 0
    | e::x::l ->  rlist := (int_of_string e,float_of_string x)::!rlist; l


let no_space str options =
  if List.mem "-no_space" options then
    String.sub str 1 (String.length str - 1)
  else
    str

let reverse str =
  let res = ref "" in
    for i = String.length str - 1 downto 0 do
      res := !res^String.make 1 (String.get str i)
    done;
    !res

let invert str options =
  if List.mem "-i" options then
    reverse str
  else
    str

let rec get_ratio cpt = function
    (file, rat)::l when cpt = file -> rat
  | e::l -> get_ratio cpt l
  | _ -> 1.

let i_o_test output files =
  if (List.length files) = 0 then
    raise (Sys_error "")
  else
    (output = "")

let rec jump = function
    0 -> ()
  | n -> Printf.printf "\n";jump (n-1)

let into_file files cpt rlist conv_string output lines colored inter =
  if inter then
    Ig_color.print_file (Conv.to_ascii
			   (Format.get (List.hd files))
			   (get_ratio !cpt rlist)
			   conv_string) output
  else
    File.save (Conv.to_ascii
		 (Format.get (List.hd files))
		 (get_ratio !cpt rlist)
		 conv_string) output colored;
  let files = List.tl files in
    List.iter (function str -> cpt := !cpt + 1; File.jump output lines;
		 File.add (Conv.to_ascii
			     (Format.get str)
			     (get_ratio !cpt rlist)
			     conv_string)
		   output)
      files

let krisboul _ = Printf.printf "Easter Egg Krisboul\n"; exit 0

let onto_screen files cpt rlist conv_string lines colored =
  Matrix.print (Conv.to_ascii
		  (Format.get (List.hd files))
		  (get_ratio !cpt rlist)
		  conv_string)
    (function x -> Shellcolor.print x colored);
(*    Matrix.print (Matrix.create 10 10 (Color.get_colored_str
				       (Color.init 0 255 0)
					"@"))
    (Color.str_output);
  *)
  let files = List.tl files in
    List.iter (function str -> cpt := !cpt + 1; jump lines;
		 Matrix.print (Conv.to_ascii
				 (Format.get str)
				 (get_ratio !cpt rlist)
				 conv_string)
		   (function x -> Shellcolor.print x colored))
      files;
    Printf.printf "\027[0m"

let treatment files output lines rlist conv_string options rev colored inter video =
  let conv_string = invert (Table.sort (reverse (no_space conv_string options))) options in
  let files = List.rev files in  
    if video then
      Video.treat (List.hd files) conv_string colored (get_ratio 1 rlist)
    else
      let cpt = ref 1 in
      let output_off = i_o_test output files in
	if not(rev) then
	  if output_off then
	    onto_screen files cpt rlist conv_string lines colored
	  else
	    into_file files cpt rlist conv_string output lines colored inter
	else
	  if output_off then
	    raise (Sys_error "File not Found")
	      (*  Printf.printf "%s\n" (File.get_string (List.hd files)) *)
	  else
	    try
	  (* Une Seule Matrice*)
	      Bmp.save (Conv.from_ascii 
			  (File.get (List.hd files) colored)
			  1. (File.get_string (List.hd files))
			  colored) output;
	    
	      Ig_color.print_file (File.get (List.hd files) colored) "spetemp"
	      
	(* Plusieurs Matrices *)
	(*
  let lst = File.get_list_mat (List.hd files) in
  let cpt = ref 0 in
  let rec treat = function
      [] -> exit 0;
    | e::l ->
	Bmp.save
	  (Conv.from_ascii
	     e
	     1.
	     (File.get_string (List.hd files)))
	  (String.concat "" (string_of_int(!cpt)::output::[]));
	cpt := !cpt + 1;
	treat l
  in
    treat lst
*)
	    with (* ERREUR a gerer ici, sur les fichiers d'entree*)
		e -> Printf.printf "%s\n" (Printexc.to_string e); exit 0

let parameters par =
  let files = ref [] in
  let output_file = ref "" in
  let line = ref 1 in
  let rlist = ref [] in
  let conv_string = ref " `.:+@" in
  let options = ref [] in
  let rev = ref false in
  let colored = ref false in
  let inter = ref false in
  let video = ref false in
  let list = "-o"::"-i"::"-l"::"-s"::"-r"::
    "-interface"::"-no_space"::"-reverse"::
    "-video"::"-color"::[] in
  let rec sort = function
      [] -> () (* Erreur Aucun parametres*)
    | "-i"::l -> options := "-i"::!options; sort l
    | "-o"::l -> sort (output_set l list output_file)
    | "-l"::l -> sort (line_set l list line)
    | "-reverse"::l -> rev := true; sort l
    | "-color"::l -> colored := true; sort l
    | "-interface"::l -> inter := true; sort l
    | "-s"::l -> sort (conv_string_set l list conv_string)
    | "-r"::l -> sort (ratio_set l list rlist)
    | "-video"::l -> video := true; sort l
    | "-no_space"::l -> options := "-no_space"::!options; sort l
    | "krisboul"::l -> krisboul ()
    | e::l -> files := e::!files; sort l
  in
    sort par;
    treatment !files !output_file !line !rlist !conv_string !options
      !rev !colored !inter !video

let main args param =
  let usg_message = "Welcome to the densha help.
Here you can see all about the densha program.
Exemple of use :
densha fisrt_entry_file second_entry_file -o output_file -r 1 4.5 -i"^
" -s .,:\\;@M -no_space\n" in
    Arg.parse
      (Arg.align args)
      (function x -> param := x::!param)
      usg_message;
    param := List.rev !param;
    try
      parameters !param
    with
	e -> Printf.printf "%s\n" (Printexc.to_string e)
(*
	_ -> Arg.usage args ("You need at least one input file
"^usg_message)
*)
let _ =
  let param = ref [] in
  let args =
    ("-o",
     Arg.Unit (function _ -> param := "-o"::!param),
     " waits for a string. Do define the output file !")::
      ("-i",
       Arg.Unit (function _ -> param := "-i"::!param),
       " Do invert the string that is used to convert an image.")::
      ("-l",
       Arg.Unit (function _ -> param := "-l"::!param),
       " waits for an integer. Do define the number of lines that seperate
differents inputs images in the output")::
      ("-s",
       Arg.Unit (function _ -> param := "-s"::!param),
       " waits for a string. Do define the string of conversion.")::
      ("-reverse",
       Arg.Unit (function _ -> param := "-reverse"::!param),
      " Reverse the convertion algorithm.")::
      ("-color",
       Arg.Unit (function _ -> param := "-color"::!param),
       " Switch the color mode on.")::
      ("-interface",
       Arg.Unit (function _ -> param := "-interface"::!param),
       " used only by the GUI, DO NOT USE !")::
      ("-video",
       Arg.Unit (function _ -> param := "-video"::!param),
       " used to see a video in ascii mode.")::
      ("-r",
       Arg.Unit (function _ -> param := "-r"::!param),
       " waits for two integers. Do define the diffent ratio, one for each file.
By default, the ratio is one.")::
      ("-no_space",
       Arg.Unit (function _ -> param := "-no_space"::!param),
       " Do delete the space character of the convert string")::[] in
    main args param
